import rclpy  # ROS 2 Python客户端库
from rclpy.action import ActionClient  # 用于创建Action客户端
from rclpy.node import Node  # 基础Node类
from action_tutorials_interfaces.action import Fibonacci  # 导入Fibonacci Action接口


class FibonacciActionClient(Node):
    """
    Fibonacci Action 客户端类，继承自 rclpy.Node
    """
    def __init__(self):
        # 初始化节点，节点名为 "fibonacci_action_client"
        super().__init__('fibonacci_action_client')

        # 创建一个 Action 客户端，用于与 Fibonacci Action 服务端通信
        # "fibonacci" 是 Action 服务端的名称，必须与服务器一致
        self._action_client = ActionClient(self, Fibonacci, 'fibonacci')

    def send_goal(self, order):
        """
        发送目标给 Action 服务端。
        参数:
            order (int): 请求生成的 Fibonacci 数列的长度。
        """
        # 打印发送目标的日志
        self.get_logger().info(f'Sending goal with order: {order}')
        
        # 创建一个 Goal 消息，并设置 order 值
        goal_msg = Fibonacci.Goal()
        goal_msg.order = order

        # 等待 Action 服务端就绪
        self._action_client.wait_for_server()

        # 异步发送目标，并设置反馈回调函数
        self._send_goal_future = self._action_client.send_goal_async(
            goal_msg,
            feedback_callback=self.feedback_callback
        )

        # 设置目标响应回调函数
        self._send_goal_future.add_done_callback(self.goal_response_callback)

    def goal_response_callback(self, future):
        """
        处理目标响应的回调函数。
        参数:
            future: 包含目标响应结果的 Future 对象。
        """
        # 获取目标句柄
        goal_handle = future.result()

        # 检查目标是否被接受
        if not goal_handle.accepted:
            self.get_logger().info('Goal rejected')  # 如果未被接受，打印日志
            return

        # 如果目标被接受，打印日志
        self.get_logger().info('Goal accepted')

        # 异步获取结果，并设置结果回调函数
        self._get_result_future = goal_handle.get_result_async()
        self._get_result_future.add_done_callback(self.result_callback)

    def feedback_callback(self, feedback_msg):
        """
        处理反馈的回调函数。
        参数:
            feedback_msg: 包含反馈消息的对象。
        """
        # 打印反馈信息，显示当前计算的 Fibonacci 部分序列
        self.get_logger().info(f'Feedback: {feedback_msg.feedback.partial_sequence}')

    def result_callback(self, future):
        """
        处理结果的回调函数。
        参数:
            future: 包含结果的 Future 对象。
        """
        # 获取最终结果
        result = future.result().result

        # 打印结果的完整 Fibonacci 数列
        self.get_logger().info(f'Result: {result.sequence}')

        # 关闭 ROS 2 节点
        rclpy.shutdown()


def main(args=None):
    """
    主函数，初始化节点并发送目标。
    """
    # 初始化 rclpy 库
    rclpy.init(args=args)

    # 创建 Fibonacci Action 客户端实例
    fibonacci_action_client = FibonacciActionClient()

    # 发送目标，生成长度为 10 的 Fibonacci 数列
    fibonacci_action_client.send_goal(order=10)

    # 开始处理节点事件循环
    rclpy.spin(fibonacci_action_client)


if __name__ == '__main__':
    main()
